all repos — caroster @ 5cebc5ee581a8c1bb7674e3b338c56de1cb5d847

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import {useTheme} from '@material-ui/core/styles';
  3import {useTranslation} from 'react-i18next';
  4import Joyride from 'react-joyride';
  5import {initializeApollo} from '../../lib/apolloClient';
  6import useToastStore from '../../stores/useToastStore';
  7import useEventStore from '../../stores/useEventStore';
  8import useTour from '../../hooks/useTour';
  9import Layout from '../../layouts/Default';
 10import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
 11import CarColumns from '../../containers/CarColumns';
 12import NewCarDialog from '../../containers/NewCarDialog';
 13import WelcomeDialog from '../../containers/WelcomeDialog';
 14import EventBar from '../../containers/EventBar';
 15import Loading from '../../containers/Loading';
 16import Fab from '../../containers/Fab';
 17import {
 18  useUpdateEventMutation,
 19  Event as EventType,
 20  useEventByUuidQuery,
 21  EventByUuidDocument,
 22  EditEventInput,
 23} from '../../generated/graphql';
 24import ErrorPage from '../_error';
 25
 26const POLL_INTERVAL = 10000;
 27
 28interface Props {
 29  event: EventType;
 30  eventUUID: string;
 31}
 32
 33const EventPage = props => {
 34  const {t} = useTranslation();
 35  const {event} = props;
 36
 37  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 38
 39  return <Event {...props} />;
 40};
 41
 42const Event = (props: Props) => {
 43  const {eventUUID} = props;
 44  const {t} = useTranslation();
 45  const theme = useTheme();
 46  const addToast = useToastStore(s => s.addToast);
 47  const setEvent = useEventStore(s => s.setEvent);
 48  const eventUpdate = useEventStore(s => s.event);
 49  const setIsEditing = useEventStore(s => s.setIsEditing);
 50  const [updateEvent] = useUpdateEventMutation();
 51  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 52  const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
 53  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 54    pollInterval: POLL_INTERVAL,
 55    variables: {uuid: eventUUID},
 56  });
 57  const {run, steps, step, onTourChange, onTourRestart} = useTour();
 58
 59  useEffect(() => {
 60    if (event) setEvent(event as EventType);
 61  }, [event]);
 62
 63  const onSave = async e => {
 64    try {
 65      const {uuid, ...data} = eventUpdate;
 66      const {id, __typename, cars, users, waitingList, ...input} = data;
 67      await updateEvent({
 68        variables: {uuid, eventUpdate: input as EditEventInput},
 69        refetchQueries: ['eventByUUID'],
 70      });
 71      setIsEditing(false);
 72    } catch (error) {
 73      console.error(error);
 74      addToast(t('event.errors.cant_update'));
 75    }
 76  };
 77
 78  const onShare = async () => {
 79    if (!event) return null;
 80    // If navigator share capability
 81    if (!!navigator.share)
 82      return await navigator.share({
 83        title: `Caroster ${event.name}`,
 84        url: `${window.location.href}`,
 85      });
 86    // Else copy URL in clipboard
 87    else if (!!navigator.clipboard) {
 88      await navigator.clipboard.writeText(window.location.href);
 89      addToast(t('event.actions.copied'));
 90      return true;
 91    }
 92  };
 93
 94  if (!event) return <Loading />;
 95
 96  return (
 97    <Layout
 98      pageTitle={t('event.title', {title: event.name})}
 99      menuTitle={t('event.title', {title: event.name})}
100      displayMenu={false}
101    >
102      <EventBar
103        event={event}
104        onAdd={setIsAddToMyEvent}
105        onSave={onSave}
106        onShare={onShare}
107        onTourRestart={onTourRestart}
108      />
109      <CarColumns toggleNewCar={toggleNewCar} />
110      <Fab open={openNewCar} onClick={toggleNewCar} aria-label="add-car" />
111      <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
112      <AddToMyEventDialog
113        event={event}
114        open={isAddToMyEvent}
115        onClose={() => setIsAddToMyEvent(false)}
116      />
117      <WelcomeDialog />
118      <Joyride
119        run={run}
120        steps={steps}
121        stepIndex={step}
122        callback={onTourChange}
123        locale={t('joyride', {returnObjects: true})}
124        continuous={true}
125        showProgress={true}
126        disableScrolling={true}
127        disableScrollParentFix={true}
128        scrollToFirstStep={false}
129        floaterProps={{
130          disableAnimation: true,
131        }}
132        styles={{
133          options: {
134            primaryColor: theme.palette.primary.main,
135          },
136          tooltipContent: {
137            whiteSpace: 'pre-wrap',
138          },
139        }}
140      />
141    </Layout>
142  );
143};
144
145export async function getServerSideProps(ctx) {
146  const {uuid} = ctx.query;
147  const apolloClient = initializeApollo();
148  const {data = {}} = await apolloClient.query({
149    query: EventByUuidDocument,
150    variables: {uuid},
151  });
152  const {eventByUUID: event} = data;
153  const {host = ''} = ctx.req.headers;
154
155  return {
156    props: {
157      event,
158      eventUUID: uuid,
159      metas: {
160        title: event?.name || '',
161        url: `https://${host}${ctx.resolvedUrl}`,
162      },
163    },
164  };
165}
166
167export default EventPage;